﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;

namespace KongMing.Project.Common
{
    public static class LibConvert
    {

        public static string GUID => Guid.NewGuid().ToString("N");
        public static bool IsNull(this string s)
        {
            return string.IsNullOrWhiteSpace(s);
        }
        public static bool NotNull(this string s)
        {
            return !string.IsNullOrWhiteSpace(s);
        }
        public static int GetRandom(int minNum, int maxNum)
        {
            var seed = BitConverter.ToInt32(Guid.NewGuid().ToByteArray(), 0);
            return new Random(seed).Next(minNum, maxNum);
        }
        public static string ToJson(this object obj)
        {
            return JsonConvert.SerializeObject(obj);
        }
        public static object GetDefaultVal(string typename)
        {
            return typename switch
            {
                "Boolean" => false,
                "DateTime" => default(DateTime),
                "Date" => default(DateTime),
                "Double" => 0.0,
                "Single" => 0f,
                "Int32" => 0,
                "String" => string.Empty,
                "Decimal" => 0m,
                _ => null,
            };
        }
        public static void CoverNull<T>(T model) where T : class
        {
            if (model == null)
            {
                return;
            }
            var typeFromHandle = typeof(T);
            var properties = typeFromHandle.GetProperties();
            var array = properties;
            for (var i = 0; i < array.Length; i++)
            {
                var propertyInfo = array[i];
                if (propertyInfo.GetValue(model, null) == null)
                {
                    propertyInfo.SetValue(model, GetDefaultVal(propertyInfo.PropertyType.Name), null);
                }
            }
        }
        public static void CoverNull<T>(List<T> models) where T : class
        {
            if (models.Count == 0)
            {
                return;
            }
            foreach (var model in models)
            {
                CoverNull(model);
            }
        }

        public static bool IsDbNull(object Obj)
        {
            return Convert.IsDBNull(Obj);
        }

        public static string String2Unicode(string source)
        {
            byte[] bytes = Encoding.Unicode.GetBytes(source);
            StringBuilder stringBuilder = new StringBuilder();
            for (int index = 0; index < bytes.Length; index += 2)
                stringBuilder.AppendFormat("\\u{0}{1}", (object)bytes[index + 1].ToString("x").PadLeft(2, '0'), (object)bytes[index].ToString("x").PadLeft(2, '0'));
            return stringBuilder.ToString();
        }

        public static string Unicode2String(string source)
        {
            return new Regex("\\\\u([0-9A-F]{4})", RegexOptions.IgnoreCase | RegexOptions.Compiled).Replace(source, (MatchEvaluator)(x => string.Empty + Convert.ToChar(Convert.ToUInt16(x.Result("$1"), 16)).ToString()));
        }

        public static long DateTimeToInt(DateTime time)
        {
            DateTime localTime = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
            return (time.Ticks - localTime.Ticks) / 10000000L;
        }

        public static long DateTimeMillisecondToInt(DateTime time)
        {
            DateTime localTime = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
            return (time.Ticks - localTime.Ticks) / 10000L;
        }

        public static DateTime IntToDateTimeMillisecond(long Millisecond)
        {
            return new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime().AddMilliseconds((double)Millisecond);
        }

        public static DateTime IntToDateTime(long Seconds)
        {
            return new DateTime(1970, 1, 1).ToLocalTime().AddSeconds((double)Seconds);
        }

        public static short StrToShort(string aStr)
        {
            if (aStr.Contains(","))
                aStr = aStr.Replace(",", "");
            short result = 0;
            short.TryParse(aStr, out result);
            return result;
        }

        public static int StrToInt(string aStr)
        {
            if (aStr.Contains(","))
                aStr = aStr.Replace(",", "");
            int result = 0;
            int.TryParse(aStr, out result);
            return result;
        }

        public static long StrToInt64(string aStr)
        {
            if (aStr.Contains(","))
                aStr = aStr.Replace(",", "");
            long result = 0;
            long.TryParse(aStr, out result);
            return result;
        }

        public static double StrToDouble(string aStr)
        {
            double result = 0.0;
            double.TryParse(aStr, out result);
            if (double.IsNaN(result))
                return 0.0;
            return result;
        }

        public static float StrToFloat(string aStr)
        {
            float result = 0.0f;
            float.TryParse(aStr, out result);
            return result;
        }

        public static Decimal StrToDecimal(string aStr)
        {
            Decimal result = new Decimal();
            Decimal.TryParse(aStr, out result);
            return result;
        }

        public static DateTime StrToDateTime(string aStr)
        {
            DateTime result = DateTime.Now;
            if (DateTime.TryParse(aStr, out result))
                return result;
            return DateTime.Now;
        }

        public static bool StrToBoolean(string aStr)
        {
            bool result;
            if (!bool.TryParse(aStr, out result))
                return false;
            return result;
        }

        public static DateTime StrToDateTime(string aStr, DateTime aDefault)
        {
            DateTime result = aDefault;
            if (DateTime.TryParse(aStr, out result))
                return result;
            return aDefault;
        }

        public static bool IntToBool(int aInt)
        {
            return aInt == 1;
        }

        public static int BoolToInt(bool aBool)
        {
            return aBool ? 1 : 0;
        }

        public static short ObjToShort(object aObj)
        {
            if (aObj == null)
                return 0;
            string s = aObj.ToString();
            if (aObj.GetType() == typeof(string) && s.Contains(","))
                s = s.Replace(",", "");
            short result = 0;
            short.TryParse(s, out result);
            return result;
        }

        public static int ObjToInt(object aObj)
        {
            if (aObj == null)
                return 0;
            if (aObj.GetType() == typeof(bool))
                return !(bool)aObj ? 0 : 1;
            string s = aObj.ToString();
            if (aObj.GetType() == typeof(string) && s.Contains(","))
                s = s.Replace(",", "");
            else if (aObj.GetType() == typeof(Decimal) || aObj.GetType() == typeof(double) || aObj.GetType() == typeof(float))
                return (int)LibConvert.ObjToDouble(aObj);
            if (s.ToLower() == "true")
                return 1;
            if (s.ToLower() == "false")
                return 0;
            int result = 0;
            int.TryParse(s, out result);
            return result;
        }

        public static long ObjToInt64(object aObj)
        {
            if (aObj == null)
                return 0;
            string s = aObj.ToString();
            if (aObj.GetType() == typeof(string) && s.Contains(","))
                s = s.Replace(",", "");
            else if (aObj.GetType() == typeof(Decimal) || aObj.GetType() == typeof(double) || aObj.GetType() == typeof(float))
                return (long)LibConvert.ObjToDouble(aObj);
            long result = 0;
            long.TryParse(s, out result);
            return result;
        }

        public static double ObjToDouble(object aObj)
        {
            if (aObj == null)
                return 0.0;
            double result = 0.0;
            double.TryParse(aObj.ToString(), out result);
            if (double.IsNaN(result))
                return 0.0;
            return result;
        }

        public static Decimal ObjToDecimal(object aObj)
        {
            if (aObj == null)
                return Decimal.Zero;
            Decimal result = new Decimal();
            Decimal.TryParse(aObj.ToString(), out result);
            return result;
        }

        public static float ObjToFloat(object aObj)
        {
            if (aObj == null)
                return 0.0f;
            float result = 0.0f;
            float.TryParse(aObj.ToString(), out result);
            return result;
        }

        public static DateTime ObjToDateTime(object aObj)
        {
            DateTime dateTime = new DateTime();
            if (aObj == null)
                return dateTime;
            try
            {
                if (aObj is DateTime)
                    return (DateTime)aObj;
                string str = LibConvert.ObjToStr(aObj);
                if (str.Length == 4)
                    return new DateTime(Convert.ToInt32(str), 1, 1);
                return Convert.ToDateTime(aObj);
            }
            catch (Exception ex)
            {
                return dateTime;
            }
        }

        public static bool ObjToBoolPython(object obj)
        {
            if (obj == null)
                return false;
            if (obj is byte)
                return (byte)obj > (byte)0;
            if (obj is bool)
                return (bool)obj;
            if (obj is int)
                return (uint)(int)obj > 0U;
            if (obj is long)
                return (ulong)(long)obj > 0UL;
            if (obj is float)
                return (double)(float)obj != 0.0;
            if (obj is Decimal)
                return (Decimal)obj != Decimal.Zero;
            if (obj is double)
                return (double)obj != 0.0;
            if (obj is string)
            {
                string lower = obj.ToString().ToLower();
                if (string.IsNullOrEmpty(lower))
                    return false;
                if (lower == "true")
                    return true;
                if (lower == "false")
                    return false;
                double result = 0.0;
                if (!double.TryParse(lower, out result))
                    return true;
                return result != 0.0;
            }
            if (obj is Array)
                return (uint)((Array)obj).Length > 0U;
            return true;
        }

        public static bool ObjToBool(object aObj)
        {
            if (aObj == null)
                return false;
            if (aObj is bool)
                return (bool)aObj;
            return aObj.ToString().ToLower() == "true" || LibConvert.ObjToInt(aObj) == 1;
        }

        public static string NullToStr(object aObj)
        {
            if (aObj == null || Convert.IsDBNull(aObj))
                return "";
            return aObj.ToString();
        }

        public static string ObjToStr(object aObj)
        {
            return LibConvert.NullToStr(aObj);
        }

        public static string MoneyToUpper(double Value, bool AState)
        {
            double num1 = LibConvert.StrToDouble(Value.ToString("0.00"));
            if (AState)
            {
                string str1;
                if (num1 < 0.0)
                {
                    num1 = -num1;
                    str1 = "负";
                }
                else
                    str1 = num1 != 0.0 ? "" : "零元零角零分";
                int num2 = (int)Math.Truncate(Math.Log(num1 + 1E-07, 10.0));
                string str2 = "";
                for (int index = num2; index >= -2; --index)
                {
                    int startIndex = (int)((long)(Math.Round(num1, 2) / Math.Pow(10.0, (double)index) + 1E-06) % 10L);
                    str2 = str2 + "零壹贰叁肆伍陆柒捌玖".Substring(startIndex, 1) + "分角元拾佰仟万拾佰仟亿拾佰仟".Substring(index + 2, 1);
                }
                return str1 + str2;
            }
            string str3;
            if (num1 < 0.0)
            {
                num1 = -num1;
                str3 = "负";
            }
            else
                str3 = num1 != 0.0 ? "" : "零元整";
            int num3 = (int)Math.Floor(Math.Log(num1 + 1E-07, 10.0));
            string str4 = "";
            bool flag = false;
            for (int index = num3; index >= -2; --index)
            {
                long num2 = (long)(Math.Round(num1, 2) / Math.Pow(10.0, (double)index) + 1E-06);
                int startIndex = (int)(num2 % 10L);
                if (startIndex == 0)
                {
                    if (index == 0 || index == 4 || index == 8)
                    {
                        str4 += "分角元拾佰仟万拾佰仟亿拾佰仟".Substring(index + 2, 1);
                        flag = false;
                    }
                    else
                        flag = true;
                }
                else
                {
                    if (flag)
                        str4 += "零壹贰叁肆伍陆柒捌玖".Substring(0, 1);
                    str4 = str4 + "零壹贰叁肆伍陆柒捌玖".Substring(startIndex, 1) + "分角元拾佰仟万拾佰仟亿拾佰仟".Substring(index + 2, 1);
                    flag = false;
                }
                if (Math.Abs(num1 - (double)num2 * Math.Pow(10.0, (double)index)) < 0.001 && index > -2 && index < 5)
                {
                    str4 = index <= 0 ? str4 + "整" : str4 + "元整";
                    break;
                }
            }
            return str3 + str4;
        }

        public static string MoneyBitUpper(double Value, int B)
        {
            string str = "";
            double num1 = LibConvert.StrToDouble(Value.ToString("0.00"));
            if (num1 < 0.0)
            {
                str = "负";
                num1 = -num1;
            }
            int num2 = (int)(num1 / Math.Pow(10.0, (double)B) + 0.001);
            if (num2 == 0)
                return "¤";
            if (num2 >= 10)
                str = "";
            int startIndex = num2 % 10;
            return str + "零壹贰叁肆伍陆柒捌玖".Substring(startIndex, 1);
        }

        public static byte[] ObjToBytes(object obj)
        {
            if (obj == null || Convert.IsDBNull(obj))
                return (byte[])null;
            if (obj.GetType() == typeof(string))
                return LibConvert.StrToBytes(obj.ToString());
            byte[] numArray = (byte[])obj;
            if (numArray.Length == 0)
                return (byte[])null;
            return numArray;
        }

        public static byte[] StrToBytes(string Str)
        {
            if (Str == null)
                return new byte[0];
            byte[] numArray = new byte[Encoding.UTF8.GetByteCount(Str)];
            return Encoding.UTF8.GetBytes(Str);
        }

        public static string BytesToStr(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                return "";
            return Encoding.UTF8.GetString(bytes).Replace("\0", string.Empty);
        }

        public static string ObjToBytesToStr(object Obj)
        {
            if (Convert.IsDBNull(Obj))
                return "";
            return Encoding.UTF8.GetString((byte[])Obj).Replace("\0", string.Empty);
        }

        public static string DatasetToXmlstr(DataSet ds)
        {
            MemoryStream memoryStream = new MemoryStream();
            memoryStream.Flush();
            ds.WriteXml((Stream)memoryStream, XmlWriteMode.WriteSchema);
            return Encoding.UTF8.GetString(memoryStream.ToArray());
        }

        public static DataSet XmlstrToDataset(string xml)
        {
            DataSet dataSet = new DataSet();
            int num = (int)dataSet.ReadXml((XmlReader)new XmlTextReader((TextReader)new StringReader(xml)));
            return dataSet;
        }

        public static string DupeString(string aC, int aN)
        {
            string str = "";
            for (int index = 1; index <= aN; ++index)
                str += aC;
            return str;
        }

        public static string LeftStr(string aStr, int aN)
        {
            string str = "";
            if (Encoding.Default.GetBytes(aStr).Length < aN)
                aStr += str.PadRight(aN - Encoding.Default.GetBytes(aStr).Length, ' ');
            byte[] bytes1 = Encoding.Default.GetBytes(aStr);
            byte[] bytes2 = new byte[aN];
            for (int index = 0; index < aN; ++index)
                bytes2[index] = bytes1[index];
            return Encoding.Default.GetString(bytes2, 0, bytes2.Length).Trim();
        }

        public static string RightStr(string aStr, int aN)
        {
            string str = "";
            if (Encoding.Default.GetBytes(aStr).Length < aN)
                aStr += str.PadLeft(aN - Encoding.Default.GetBytes(aStr).Length, ' ');
            byte[] bytes1 = Encoding.Default.GetBytes(aStr);
            byte[] bytes2 = new byte[aN];
            int num = Encoding.Default.GetBytes(aStr).Length - 1;
            for (int index = aN - 1; index >= 0; --index)
                bytes2[index] = bytes1[num--];
            return Encoding.Default.GetString(bytes2, 0, bytes2.Length).Trim();
        }

        public static string Right(string aStr, int aN)
        {
            string str = "";
            if (aStr.Length < aN)
                aStr += str.PadLeft(aN - aStr.Length, ' ');
            return aStr.Substring(aStr.Length - aN, aN);
        }

        public static int GetLength(string aStr)
        {
            return Encoding.Default.GetBytes(aStr).Length;
        }

        public static string BytesToByteStr(IEnumerable<byte> bs)
        {
            if (bs == null)
                return "";
            StringBuilder stringBuilder = new StringBuilder();
            foreach (byte b in bs)
            {
                string str = b.ToString("x2");
                stringBuilder.Append(str);
            }
            return stringBuilder.ToString();
        }

        public static string DateToNlDate(DateTime Dt)
        {
            ChineseLunisolarCalendar lunisolarCalendar = new ChineseLunisolarCalendar();
            int year = lunisolarCalendar.GetYear(Dt);
            int month = lunisolarCalendar.GetMonth(Dt);
            int dayOfMonth = lunisolarCalendar.GetDayOfMonth(Dt);
            int leapMonth = lunisolarCalendar.GetLeapMonth(year);
            if (leapMonth > 0)
            {
                if (leapMonth == month)
                    --month;
                else if (month > leapMonth)
                    --month;
            }
            return year.ToString() + "-" + month.ToString("00") + "-" + dayOfMonth.ToString("00");
        }

        public static string StrAddNumber(string Source, int Number)
        {
            if (Number == 0)
                return Source;
            if (Source == "")
                return Number.ToString();
            string str = "";
            string aStr = "";
            for (int index = Source.Length - 1; index >= 0; --index)
            {
                if (char.IsNumber(Source[index]))
                {
                    aStr = Source[index].ToString() + aStr;
                }
                else
                {
                    str = Source.Substring(0, index + 1);
                    break;
                }
            }
            if (Source == str)
                return Source;
            long num = LibConvert.StrToInt64(aStr) + (long)Number;
            return str + LibConvert.DupeString("0", aStr.Length - num.ToString().Length) + num.ToString();
        }

        public static int GetRandomNumeric(int aMin, int aMax)
        {
            return new Random((int)DateTime.Now.Ticks).Next(aMin, aMax);
        }

        public static List<long> ToLongList(this string[] stringList)
        {
            List<long> longList = new List<long>();
            foreach (string s in stringList)
            {
                long num = 0;
                ref long local = ref num;
                long.TryParse(s, out local);
                longList.Add(num);
            }
            return longList;
        }

        public static List<long> ToLongList(this List<string> source)
        {
            long result = 0;
            List<long> longList = new List<long>();
            foreach (string s in source)
            {
                long.TryParse(s, out result);
                longList.Add(result);
            }
            return longList;
        }

        public static DataTable ConvertToDataTable<T>(this List<T> items)
        {
            DataTable dataTable = new DataTable(typeof(T).Name);
            PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public);
            foreach (PropertyInfo propertyInfo in properties)
            {
                Type coreType = LibConvert.GetCoreType(propertyInfo.PropertyType);
                dataTable.Columns.Add(propertyInfo.Name, coreType);
            }
            foreach (T obj in items)
            {
                object[] objArray = new object[properties.Length];
                for (int index = 0; index < properties.Length; ++index)
                    objArray[index] = properties[index].GetValue((object)obj, (object[])null);
                dataTable.Rows.Add(objArray);
            }
            return dataTable;
        }

        private static bool IsNullable(Type t)
        {
            if (!t.IsValueType)
                return true;
            if (t.IsGenericType)
                return t.GetGenericTypeDefinition() == typeof(Nullable<>);
            return false;
        }

        private static Type GetCoreType(Type t)
        {
            if (t != (Type)null && LibConvert.IsNullable(t) && t.IsValueType)
                return Nullable.GetUnderlyingType(t);
            return t;
        }
    }
}
